/*******************************************************************************
* Project: QSAR(Cute Software Architecture) 
*
* Copyright: Copyright(C) 2024 by YuetingBen, All Rights Reserved
*
* File name: CanNm.c
*
* Brief: ;
*
* Author: Yueting.Ben
*
* Module: CanNm
*
*******************************************************************************/

/** HEADER FILES **/
#include "CanNm.h"


/** MACRO DEFINITION **/
#define NM_STATE_ENTER_NETWORKMODE ((Nm_StateType)0x08)  /* Enter Network Mode State */

#define CANNM_CBV_BYTE canNmChannelConfigPtr->CanNmTxPduRef->CanNmTxPduRef->MetaDataTypeRef->MetaDataItem[canNmChannelConfigPtr->CanNmPduCbvPosition]
#define CANNM_CBV_REPEAT_MESSAGE_REQUEST_SET (CANNM_CBV_BYTE |= 0x01)
#define CANNM_CBV_REPEAT_MESSAGE_REQUEST_CLEAR (CANNM_CBV_BYTE &= 0xFE)
#define CANNM_CBV_PN_SHUTDOWN_REQUEST_SET (CANNM_CBV_BYTE |= 0x02)
#define CANNM_CBV_PN_SHUTDOWN_REQUEST_CLEAR (CANNM_CBV_BYTE &= 0xFD)
#define CANNM_CBV_NM_COORDIANTE_OR_SLEEP_READY_SET (CANNM_CBV_BYTE |= 0x04)
#define CANNM_CBV_NM_COORDIANTE_OR_SLEEP_READY_CLEAR (CANNM_CBV_BYTE &= 0xF7)
#define CANNM_CBV_ACTIVE_WAKEUP_SET (CANNM_CBV_BYTE |= 0x10)
#define CANNM_CBV_ACTIVE_WAKEUP_CLEAR (CANNM_CBV_BYTE &= 0xEF)
#define CANNM_CBV_PARTIAL_NETWORK_LEARNING_SET (CANNM_CBV_BYTE |= 0x20)
#define CANNM_CBV_PARTIAL_NETWORK_LEARNING_CLEAR (CANNM_CBV_BYTE &= 0xDF)
#define CANNM_CBV_PARTIAL_NETWORK_INFORMAT_SET (CANNM_CBV_BYTE |= 0x40)
#define CANNM_CBV_PARTIAL_NETWORK_INFORMAT_CLEAR (CANNM_CBV_BYTE &= 0xBF)


/** TYPEDEF DEFINITION **/
typedef uint8 CanNmTriggerRequestType;
#define CANNM_TRIGGER_NONE ((CanNmTriggerRequestType)0x00)
#define CANNM_TRIGGER_REQUEST ((CanNmTriggerRequestType)0x01)
#define CANNM_TRIGGER_RELEASE ((CanNmTriggerRequestType)0x02)
#define CANNM_TRIGGER_REPEAT_REQUEST ((CanNmTriggerRequestType)0x03)
#define CANNM_TRIGGER_PASSIVE_STARTUP ((CanNmTriggerRequestType)0x04)

typedef struct
{
    Nm_StateType NmState;
    uint8 ImmediateCycleNum;
    CanNmTriggerRequestType CanNmTriggerRequest; 
}CanNm_InfoType;


/** LOCAL DATA DECLARATION **/
static CanNm_InfoType CanNm_Info[CanNmConf_NetworkHandleId_Max];


/** GLOBAL DATA DECLARATION **/


/** LOCAL FUNCTION DECLARATION **/


/** GLOBAL FUNCTION DECLARATION **/

Std_ReturnType CanNm_PassiveStartUp(
    NetworkHandleType nmChannelHandle
);

Std_ReturnType CanNm_NetworkRequest(
    NetworkHandleType nmChannelHandle
);

Std_ReturnType CanNm_NetworkRelease(
    NetworkHandleType nmChannelHandle
);

Std_ReturnType CanNm_DisableCommunication(
    NetworkHandleType nmChannelHandle
);

Std_ReturnType CanNm_EnableCommunication(
    NetworkHandleType nmChannelHandle
);

Std_ReturnType CanNm_SetUserData(
    NetworkHandleType nmChannelHandle, 
    const uint8* nmUserDataPtr
);

Std_ReturnType CanNm_GetUserData(
    NetworkHandleType nmChannelHandle, 
    uint8* nmUserDataPtr
);

Std_ReturnType CanNm_Transmit(
    PduIdType TxPduId, 
    const PduInfoType* PduInfoPtr
);

Std_ReturnType CanNm_GetNodeIdentifier(
    NetworkHandleType nmChannelHandle, 
    uint8* nmNodeIdPtr
);

Std_ReturnType CanNm_GetLocalNodeIdentifier(
    NetworkHandleType nmChannelHandle, 
    uint8* nmNodeIdPtr
);

Std_ReturnType CanNm_RepeatMessageRequest(
    NetworkHandleType nmChannelHandle
);

Std_ReturnType CanNm_GetPduData(
    NetworkHandleType nmChannelHandle, 
    uint8* nmPduDataPtr
);

Std_ReturnType CanNm_GetState(
    NetworkHandleType nmChannelHandle, 
    Nm_StateType* nmStatePtr, 
    Nm_ModeType* nmModePtr
);

Std_ReturnType CanNm_SetSleepReadyBit(
    NetworkHandleType nmChannelHandle, 
    boolean nmSleepReadyBit
);

Std_ReturnType CanNm_PnLearningRequest(
    NetworkHandleType nmChannelHandle
);

void CanNm_TxConfirmation(
    PduIdType TxPduId, 
    Std_ReturnType result
);

void CanNm_RxIndication(
    PduIdType RxPduId, 
    const PduInfoType* PduInfoPtr
);

Std_ReturnType CanNm_TriggerTransmit(
    PduIdType TxPduId, 
    PduInfoType* PduInfoPtr
);

void CanNm_GetVersionInfo(
    Std_VersionInfoType* versionInfo
);

void CanNm_Init(
    const CanNm_ConfigType* cannmConfigPtr
);

void CanNm_MainFunction(
    void
);



/** LOCAL DATA **/
static CanNm_InfoType CanNm_Info[CanNmConf_NetworkHandleId_Max] = {0x00};


/** GLOBAL DATA **/


/** LOCAL FUNCTION **/


/** GLOBAL FUNCTION **/

/*******************************************************************************
* -Name            CanNm_PassiveStartUp
* -Brief           Passive startup of the AUTOSAR CAN NM.  
* -Details         It triggers the transition from Bus-Sleep Mode or Prepare Bus Sleep Mode to the Network Mode in Repeat Message State.
*                  Caveats: CanNm is initialized correctly
* -Param[in]       nmChannelHandle: Identification of the NM-channel
* -Param[out]      None
* -Return          None          
*******************************************************************************/
Std_ReturnType CanNm_PassiveStartUp(
    NetworkHandleType nmChannelHandle
)
{
    Std_ReturnType retVal = E_OK;
    CanNm_InfoType* canNmInfoPtr = (CanNm_InfoType*)&CanNm_Info[nmChannelHandle];

    canNmInfoPtr->CanNmTriggerRequest = CANNM_TRIGGER_PASSIVE_STARTUP;
    
    return(retVal);
}

/*******************************************************************************
* -Name            CanNm_NetworkRequest
* -Brief           Request the network, since ECU needs to communicate on the bus 
* -Details         None
* -Param[in]       nmChannelHandle: Identification of the NM-channel
* -Param[out]      None
* -Return          E_OK: No error
*                  E_NOT_OK: Requesting of network has failed
*******************************************************************************/
Std_ReturnType CanNm_NetworkRequest(
    NetworkHandleType nmChannelHandle
)
{
    Std_ReturnType retVal = E_OK;
    CanNm_InfoType* canNmInfoPtr = (CanNm_InfoType*)&CanNm_Info[nmChannelHandle];

    canNmInfoPtr->CanNmTriggerRequest = CANNM_TRIGGER_REQUEST;

    return(retVal);
}

/*******************************************************************************
* -Name            CanNm_NetworkRelease
* -Brief           Release the network, since ECU doesn't have to communicate on the bus 
* -Details         None
* -Param[in]       nmChannelHandle: Identification of the NM-channel
* -Param[out]      None
* -Return          E_OK: No error
*                  E_NOT_OK: Releasing of network has failed
*******************************************************************************/
Std_ReturnType CanNm_NetworkRelease(
    NetworkHandleType nmChannelHandle
)
{
    Std_ReturnType retVal = E_OK;
    CanNm_InfoType* canNmInfoPtr = (CanNm_InfoType*)&CanNm_Info[nmChannelHandle];

    canNmInfoPtr->CanNmTriggerRequest = CANNM_TRIGGER_RELEASE;
    
    return(retVal);
}


/*******************************************************************************
* -Name            CanNm_DisableCommunication
* -Brief           Disable the NM PDU transmission ability due to a ISO14229 Communication Control (28hex) service 
* -Details         None
* -Param[in]       nmChannelHandle: Identification of the NM-channel
* -Param[out]      None
* -Return          E_OK: No error
*                  E_NOT_OK: Disabling of NM PDU transmission ability has failed
*******************************************************************************/
Std_ReturnType CanNm_DisableCommunication(
    NetworkHandleType nmChannelHandle
)
{
    
}

/*******************************************************************************
* -Name            CanNm_EnableCommunication
* -Brief           Enable the NM PDU transmission ability due to a ISO14229 Communication Control (28hex) service 
* -Details         None
* -Param[in]       nmChannelHandle: Identification of the NM-channel
* -Param[out]      None
* -Return          E_OK: No error
*                  E_NOT_OK: Enabling of NM PDU transmission ability has failed
*******************************************************************************/
Std_ReturnType CanNm_EnableCommunication(
    NetworkHandleType nmChannelHandle
)
{
    
}

/*******************************************************************************
* -Name            CanNm_SetUserData
* -Brief           Set user data for NM PDUs transmitted next on the bus 
* -Details         None
* -Param[in]       nmChannelHandle: Identification of the NM-channel
* -Param[in]       nmUserDataPtr: Pointer where the user data for the next transmitted NM PDU shall be copied from
* -Param[out]      None
* -Return          E_OK: No error
*                  E_NOT_OK: E_NOT_OK: Setting of user data has failed
*******************************************************************************/
Std_ReturnType CanNm_SetUserData(
    NetworkHandleType nmChannelHandle, 
    const uint8* nmUserDataPtr
)
{
    
}

/*******************************************************************************
* -Name            CanNm_GetUserData
* -Brief           Set user data for NM PDUs transmitted next on the bus 
* -Details         None
* -Param[in]       nmChannelHandle: Identification of the NM-channel
* -Param[out]      nmUserDataPtr: Pointer where user data out of the most recently received NM PDU shall be copied to
* -Return          E_OK: No error
*                  E_NOT_OK: Getting of user data has failed
*******************************************************************************/
Std_ReturnType CanNm_GetUserData(
    NetworkHandleType nmChannelHandle, 
    uint8* nmUserDataPtr
)
{
    
}

/*******************************************************************************
* -Name            CanNm_Transmit
* -Brief           Requests transmission of a PDU 
* -Details         None
* -Param[in]       TxPduId: Identifier of the PDU to be transmitted
* -Param[out]      PduInfoPtr: Length of and pointer to the PDU data and pointer to MetaData
* -Return          E_OK: Transmit request has been accepted
*                  E_NOT_OK: Transmit request has not been accepted
*******************************************************************************/
Std_ReturnType CanNm_Transmit(
    PduIdType TxPduId, 
    const PduInfoType* PduInfoPtr
)
{
    
}


/*******************************************************************************
* -Name            CanNm_GetNodeIdentifier
* -Brief           Get node identifier out of the most recently received NM PDU 
* -Details         None
* -Param[in]       nmChannelHandle: Identification of the NM-channel
* -Param[out]      nmNodeIdPtr: Pointer where node identifier out of the most recently received NM PDU shall be copied to
* -Return          E_OK: No error
*                  E_NOT_OK: Getting of the node identifier out of the most recently received NM PDU has failed 
*                            or is not configured for this network handle.
*******************************************************************************/
Std_ReturnType CanNm_GetNodeIdentifier(
    NetworkHandleType nmChannelHandle, 
    uint8* nmNodeIdPtr
)
{
    
}

/*******************************************************************************
* -Name            CanNm_GetLocalNodeIdentifier
* -Brief           Get node identifier configured for the local node. 
* -Details         None
* -Param[in]       nmChannelHandle: Identification of the NM-channel
* -Param[out]      nmNodeIdPtr: Pointer where node identifier of the local node shall be copied to
* -Return          E_OK: No error
*                  E_NOT_OK: Getting of the node identifier of the local node has failed or is not 
*                            configured for this network handle
*******************************************************************************/
Std_ReturnType CanNm_GetLocalNodeIdentifier(
    NetworkHandleType nmChannelHandle, 
    uint8* nmNodeIdPtr
)
{
    
}

/*******************************************************************************
* -Name            CanNm_RepeatMessageRequest
* -Brief           Set Repeat Message Request Bit for NM PDUs transmitted next on the bus 
* -Details         None
* -Param[in]       nmChannelHandle: Identification of the NM-channel
* -Param[out]      None
* -Return          E_OK: No error
*                  E_NOT_OK: Setting of Repeat Message Request Bit has failed or is not configured for this network handle
*******************************************************************************/
Std_ReturnType CanNm_RepeatMessageRequest(
    NetworkHandleType nmChannelHandle
)
{
    Std_ReturnType retVal = E_OK;
    CanNm_InfoType* canNmInfoPtr = (CanNm_InfoType*)&CanNm_Info[nmChannelHandle];

    canNmInfoPtr->CanNmTriggerRequest = CANNM_TRIGGER_REPEAT_REQUEST;

    return(retVal);
}

/*******************************************************************************
* -Name            CanNm_GetPduData
* -Brief           Get the whole PDU data out of the most recently received NM PDU 
* -Details         None
* -Param[in]       nmChannelHandle: Identification of the NM-channel
* -Param[out]      nmPduDataPtr: Pointer where NM PDU shall be copied to
* -Return          E_OK: No error
*                  E_NOT_OK: Getting of NM PDU Data has failed or is not configured for this network handle
*******************************************************************************/
Std_ReturnType CanNm_GetPduData(
    NetworkHandleType nmChannelHandle, 
    uint8* nmPduDataPtr
)
{
    
}

/*******************************************************************************
* -Name            CanNm_GetState
* -Brief           Returns the state and the mode of the network management 
* -Details         None
* -Param[in]       nmChannelHandle: Identification of the NM-channel
* -Param[out]      nmStatePtr: Pointer where state of the network management shall be copied to
* -Param[out]      nmModePtr: Pointer where the mode of the network management shall be copied to
* -Return          E_OK: No error
*                  E_NOT_OK: Getting of NM state has failed
*******************************************************************************/
Std_ReturnType CanNm_GetState(
    NetworkHandleType nmChannelHandle, 
    Nm_StateType* nmStatePtr, 
    Nm_ModeType* nmModePtr
)
{
    Std_ReturnType retVal = E_OK;
    
    CanNm_InfoType* canNmInfoPtr = (CanNm_InfoType*)&CanNm_Info[nmChannelHandle];

    *nmStatePtr = canNmInfoPtr->NmState;

    return(retVal);
}


/*******************************************************************************
* -Name            CanNm_SetSleepReadyBit
* -Brief           Set the NM Coordinator Sleep Ready bit in the Control Bit Vector 
* -Details         None
* -Param[in]       nmChannelHandle: Identification of the NM-channel
* -Param[in]       nmSleepReadyBit: Value written to ReadySleep Bit in CBV
* -Param[out]      None
* -Return          E_OK: No error
*                  E_NOT_OK: Writing of remote sleep indication bit has failed
*******************************************************************************/
Std_ReturnType CanNm_SetSleepReadyBit(
    NetworkHandleType nmChannelHandle, 
    boolean nmSleepReadyBit
)
{
    
}

/*******************************************************************************
* -Name            CanNm_PnLearningRequest
* -Brief           Set Repeat Message Request Bit and Partial Network Learning Bit for NM messages
* -Details         Set Repeat Message Request Bit and Partial Network Learning Bit for NM messages transmitted next 
*                  on the bus. This will force all nodes to enter the PNC Learning Phase. This is needed for the optional 
*                  Dynamic PNC-to-channel-mapping feature
* -Param[in]       nmChannelHandle: Identification of the NM-channel
* -Param[out]      None
* -Return          E_OK: No error
*                  E_NOT_OK: PN Learning Requesthas failed or is not configured for this network handle
*******************************************************************************/
Std_ReturnType CanNm_PnLearningRequest(
    NetworkHandleType nmChannelHandle
)
{
    
}

/*******************************************************************************
* -Name            CanNm_TxConfirmation
* -Brief           The lower layer communication interface module confirms the transmission of a PDU, 
*                  or the failure to transmit a PDU 
* -Details         None
* -Param[in]       TxPduId: ID of the PDU that has been transmitted
* -Param[in]       result: E_OK: The PDU was transmitted. E_NOT_OK: Transmission of the PDU failed
* -Param[out]      None
* -Return          None
*******************************************************************************/
void CanNm_TxConfirmation(
    PduIdType TxPduId, 
    Std_ReturnType result
)
{
    
}

/*******************************************************************************
* -Name            CanNm_RxIndication
* -Brief           Indication of a received PDU from a lower layer communication interface module. 
* -Details         None
* -Param[in]       RxPduId: ID of the received PDU
* -Param[in]       PduInfoPtr: Contains the length (SduLength) of the received PDU, 
                   a pointer to a buffer (SduDataPtr) containing the PDU, and the MetaData related to this PDU.
* -Param[out]      None
* -Return          None
*******************************************************************************/
void CanNm_RxIndication(
    PduIdType RxPduId, 
    const PduInfoType* PduInfoPtr
)
{    
    NetworkHandleType nmChannelHandle = CanNmConf_NetworkHandleId_0;
    CanNm_InfoType* canNmInfoPtr = (CanNm_InfoType*)&CanNm_Info[nmChannelHandle];
    CanNmChannelConfigType* canNmChannelConfigPtr = (CanNmChannelConfigType*)&CanNmChannelConfig[nmChannelHandle];

    /* Start Wait Bus-Sleep Timer */
    Tm_StartTimer(TmConf_TimerChannel_NMTimeoutTimer, canNmChannelConfigPtr->CanNmTimeoutTime);

    if((NM_STATE_BUS_SLEEP == canNmInfoPtr->NmState) || (NM_STATE_PREPARE_BUS_SLEEP == canNmInfoPtr->NmState))
    {
        CanNm_PassiveStartUp(nmChannelHandle);
    }
}

/*******************************************************************************
* -Name            CanNm_TriggerTransmit
* -Brief           None 
* -Details         Within this API, the upper layer module (called module) shall check whether the available data fits into 
*                  the buffer size reported by PduInfoPtr->SduLength. If it fits, it shall copy its data into the buffer 
*                  provided by PduInfoPtr->SduDataPtr and update the length of the actual copied data in PduInfoPtr->SduLength. 
*                  If not, it returns E_NOT_OK without changing PduInfoPtr
* -Param[in]       TxPduId: ID of the SDU that is requested to be transmitted.
* -Param[inout]    PduInfoPtr: Contains a pointer to a buffer (SduDataPtr) to where the SDU data shall be copied, 
*                  and the available buffer size in SduLengh. On return, the service will indicate the length of 
*                  the copied SDU data in SduLength
* -Param[out]      None
* -Return          E_OK: SDU has been copied and SduLength indicates the number of copied bytes
*                  E_NOT_OK: No SDU data has been copied. PduInfoPtr must not be used since it may contain a NULL pointer or point to invalid data
*******************************************************************************/
Std_ReturnType CanNm_TriggerTransmit(
    PduIdType TxPduId, 
    PduInfoType* PduInfoPtr
)
{
    
}

/*******************************************************************************
* -Name            CanNm_GetVersionInfo
* -Brief           Returns the version information of this module 
* -Details         None
* -Param[out]      versioninfo: Pointer to the version information of this module
* -Return          None          
*******************************************************************************/
void CanNm_GetVersionInfo(
    Std_VersionInfoType* versionInfo
)
{
    versionInfo->vendorID = (uint16)YSAR_VENDOR_ID;
    versionInfo->moduleID = (uint8)CANNM_MODULE_ID;
    versionInfo->sw_major_version = (uint8)CANNM_SW_MAJOR_VERSION;
    versionInfo->sw_minor_version = (uint8)CANNM_SW_MINOR_VERSION;
    versionInfo->sw_patch_version = (uint8)CANNM_SW_PATCH_VERSION;
}

/*******************************************************************************
* -Name            CanNm_Init
* -Brief           Initialize the CanNm module 
* -Details         None
* -Param[in]       cannmConfigPtr: Pointer to a selected configuration structure
* -Param[out]      None
* -Return          None          
*******************************************************************************/
void CanNm_Init(
    const CanNm_ConfigType* cannmConfigPtr
)
{
    NetworkHandleType nmChannelHandle;

    nmChannelHandle = CanNmConf_NetworkHandleId_0;
    CanNm_InfoType* canNmInfoPtr = (CanNm_InfoType*)&CanNm_Info[nmChannelHandle];
    CanNmChannelConfigType* canNmChannelConfigPtr = (CanNmChannelConfigType*)&CanNmChannelConfig[nmChannelHandle];

    canNmInfoPtr->NmState = NM_STATE_BUS_SLEEP;
    canNmInfoPtr->ImmediateCycleNum = canNmChannelConfigPtr->CanNmImmediateNmTransmissions;

    canNmChannelConfigPtr->CanNmTxPduRef->CanNmTxPduRef->MetaDataTypeRef->MetaDataItem[canNmChannelConfigPtr->CanNmPduNidPosition] = canNmChannelConfigPtr->CanNmNodeId;
    canNmChannelConfigPtr->CanNmTxPduRef->CanNmTxPduRef->MetaDataTypeRef->MetaDataItem[canNmChannelConfigPtr->CanNmPduCbvPosition] = 0x00;
}

/*******************************************************************************
* -Name            CanNm_MainFunction
* -Brief           Main function of the CanNm which processes the algorithm describes in that document 
* -Details         None
* -Param[in]       None
* -Param[out]      None
* -Return          None          
*******************************************************************************/
void CanNm_MainFunction(
    void
)
{
    NetworkHandleType nmChannelHandle = CanNmConf_NetworkHandleId_0;
    PduInfoType PduInfo;
    CanNm_InfoType* canNmInfoPtr = (CanNm_InfoType*)&CanNm_Info[nmChannelHandle];
    CanNmChannelConfigType* canNmChannelConfigPtr = (CanNmChannelConfigType*)&CanNmChannelConfig[nmChannelHandle];
    uint8 timerExpiredStatus = RESET;
    
    switch(canNmInfoPtr->NmState)
    {
        case NM_STATE_BUS_SLEEP:
        {
            if((CANNM_TRIGGER_REQUEST == canNmInfoPtr->CanNmTriggerRequest)
              || (CANNM_TRIGGER_PASSIVE_STARTUP == canNmInfoPtr->CanNmTriggerRequest))
            {
                if(CANNM_TRIGGER_REQUEST == canNmInfoPtr->CanNmTriggerRequest)
                {
                    canNmInfoPtr->ImmediateCycleNum = 0u;
                    CANNM_CBV_ACTIVE_WAKEUP_SET;
                }
                canNmInfoPtr->NmState = NM_STATE_ENTER_NETWORKMODE;
            }

            break;
        }
        case NM_STATE_PREPARE_BUS_SLEEP:
        {
            /* Wait Bus-Sleep Timer has expired, to Prepare Bus-Sleep Mode */
            Tm_GetTimerExpiredStatus(TmConf_TimerChannel_NMTimeoutTimer, (uint8*)&timerExpiredStatus);
            if(SET == timerExpiredStatus)
            {
                canNmInfoPtr->NmState = NM_STATE_BUS_SLEEP;
                Nm_BusSleepMode(nmChannelHandle);
            }

            if((CANNM_TRIGGER_REQUEST == canNmInfoPtr->CanNmTriggerRequest)
              || (CANNM_TRIGGER_PASSIVE_STARTUP == canNmInfoPtr->CanNmTriggerRequest))
            {
                if(CANNM_TRIGGER_REQUEST == canNmInfoPtr->CanNmTriggerRequest)
                {
                    canNmInfoPtr->ImmediateCycleNum = 0u;
                    CANNM_CBV_ACTIVE_WAKEUP_SET;
                }
                canNmInfoPtr->NmState = NM_STATE_ENTER_NETWORKMODE;
            }
            
            break;
        }
        case NM_STATE_ENTER_NETWORKMODE:
        {
            canNmInfoPtr->NmState = NM_STATE_REPEAT_MESSAGE;

            /* Start Repeat Message Timer */
            Tm_StartTimer(TmConf_TimerChannel_RepeatMessageTimer, canNmChannelConfigPtr->CanNmRepeatMessageTime);

            /* Start NM-Timeout Timer */
            Tm_StartTimer(TmConf_TimerChannel_NMTimeoutTimer, canNmChannelConfigPtr->CanNmTimeoutTime);
            
            Nm_NetworkMode(nmChannelHandle);
            break;
        }
        case NM_STATE_REPEAT_MESSAGE:
        {
            /* Tx Timeout Timer has expired, Nm_TxTimeoutException */
            Tm_GetTimerExpiredStatus(TmConf_TimerChannel_TxTimeoutTimer, (uint8*)&timerExpiredStatus);
            if(SET == timerExpiredStatus)
            {
                if(canNmInfoPtr->ImmediateCycleNum < canNmChannelConfigPtr->CanNmImmediateNmTransmissions)
                {
                    canNmInfoPtr->ImmediateCycleNum++;
                    Tm_StartTimer(TmConf_TimerChannel_TxTimeoutTimer, canNmChannelConfigPtr->CanNmImmediateNmCycleTime);
                }
                else
                {
                    Tm_StartTimer(TmConf_TimerChannel_TxTimeoutTimer, canNmChannelConfigPtr->CanNmMsgCycleTime);
                }
                
                CANNM_CBV_REPEAT_MESSAGE_REQUEST_SET;
                PduInfo.SduLength = (uint16)canNmChannelConfigPtr->CanNmTxPduRef->CanNmTxPduRef->PduLength;
                PduInfo.SduDataPtr = canNmChannelConfigPtr->CanNmTxPduRef->CanNmTxPduRef->MetaDataTypeRef->MetaDataItem;
                CanIf_Transmit(canNmChannelConfigPtr->CanNmTxPduRef->LowLayerPduId, (PduInfoType*)&PduInfo);

                Nm_TxTimeoutException(nmChannelHandle);
            }
            
            /* Repeat Message Timer has expired, Network Requested to Normal Operation State, Network Released to Ready Sleep State */
            Tm_GetTimerExpiredStatus(TmConf_TimerChannel_RepeatMessageTimer, (uint8*)&timerExpiredStatus);
            if(SET == timerExpiredStatus)
            {
                Tm_GetTimerExpiredStatus(TmConf_TimerChannel_NMTimeoutTimer, (uint8*)&timerExpiredStatus);
                if(RESET == timerExpiredStatus)
                {
                    canNmInfoPtr->NmState = NM_STATE_NORMAL_OPERATION;
                }
                else
                {
                    canNmInfoPtr->NmState = NM_STATE_READY_SLEEP;
                }
                CANNM_CBV_ACTIVE_WAKEUP_CLEAR;
                CANNM_CBV_REPEAT_MESSAGE_REQUEST_CLEAR;
            }

            /* NM-Timeout Timer has expired, Start NM-Timeout Timer */
            Tm_GetTimerExpiredStatus(TmConf_TimerChannel_NMTimeoutTimer, (uint8*)&timerExpiredStatus);
            if(SET == timerExpiredStatus)
            {
                Tm_StartTimer(TmConf_TimerChannel_NMTimeoutTimer, canNmChannelConfigPtr->CanNmTimeoutTime);
            }

            break;
        }
        case NM_STATE_NORMAL_OPERATION:
        {
            /* Tx Timeout Timer has expired, Nm_TxTimeoutException */
            Tm_GetTimerExpiredStatus(TmConf_TimerChannel_TxTimeoutTimer, (uint8*)&timerExpiredStatus);
            if(SET == timerExpiredStatus)
            {
                Tm_StartTimer(TmConf_TimerChannel_TxTimeoutTimer, canNmChannelConfigPtr->CanNmMsgCycleTime);

                PduInfo.SduLength = (uint16)canNmChannelConfigPtr->CanNmTxPduRef->CanNmTxPduRef->PduLength;
                PduInfo.SduDataPtr = canNmChannelConfigPtr->CanNmTxPduRef->CanNmTxPduRef->MetaDataTypeRef->MetaDataItem;
                CanIf_Transmit(canNmChannelConfigPtr->CanNmTxPduRef->LowLayerPduId, (PduInfoType*)&PduInfo);

                Nm_TxTimeoutException(nmChannelHandle);
            }

            /* NM-Timeout Timer has expired, Start NM-Timeout Timer */
            Tm_GetTimerExpiredStatus(TmConf_TimerChannel_NMTimeoutTimer, (uint8*)&timerExpiredStatus);
            if(SET == timerExpiredStatus)
            {
                Tm_StartTimer(TmConf_TimerChannel_NMTimeoutTimer, canNmChannelConfigPtr->CanNmTimeoutTime);
            }

            if(CANNM_TRIGGER_REPEAT_REQUEST == canNmInfoPtr->CanNmTriggerRequest)
            {
                canNmInfoPtr->NmState = NM_STATE_REPEAT_MESSAGE;
                /* Start Repeat Message Timer */
                Tm_StartTimer(TmConf_TimerChannel_RepeatMessageTimer, canNmChannelConfigPtr->CanNmRepeatMessageTime);
            }
            else if(CANNM_TRIGGER_RELEASE == canNmInfoPtr->CanNmTriggerRequest)
            {
                canNmInfoPtr->NmState = NM_STATE_READY_SLEEP;
            }
            else
            {
                /* Do nothing */
            }

            break;
        }
        case NM_STATE_READY_SLEEP:
        {
            /* NM-Timeout Timer has expired, to Prepare Bus-Sleep Mode */
            Tm_GetTimerExpiredStatus(TmConf_TimerChannel_NMTimeoutTimer, (uint8*)&timerExpiredStatus);
            if(SET == timerExpiredStatus)
            {
                canNmInfoPtr->NmState = NM_STATE_PREPARE_BUS_SLEEP;

                /* Start Wait Bus-Sleep Timer */
                Tm_StartTimer(TmConf_TimerChannel_NMTimeoutTimer, canNmChannelConfigPtr->CanNmWaitBusSleepTime);

                Nm_PrepareBusSleepMode(nmChannelHandle);
            }

            if(CANNM_TRIGGER_REQUEST == canNmInfoPtr->CanNmTriggerRequest)
            {
                canNmInfoPtr->NmState = NM_STATE_NORMAL_OPERATION;
            }
            else if(CANNM_TRIGGER_REPEAT_REQUEST == canNmInfoPtr->CanNmTriggerRequest)
            {
                canNmInfoPtr->NmState = NM_STATE_REPEAT_MESSAGE;
                /* Start Repeat Message Timer */
                Tm_StartTimer(TmConf_TimerChannel_RepeatMessageTimer, canNmChannelConfigPtr->CanNmRepeatMessageTime);
            }
            else
            {
                /* Do nothing */
            }

            break;
        }
        default:
        {
            break;
        } 
    }
    canNmInfoPtr->CanNmTriggerRequest = CANNM_TRIGGER_NONE;
}


/* Testing interface */
void CanNm_TriggerRequest(
    uint8 Request
)
{
    NetworkHandleType nmChannelHandle = CanNmConf_NetworkHandleId_0;
    PduInfoType PduInfo;
    CanNm_InfoType* canNmInfoPtr = (CanNm_InfoType*)&CanNm_Info[nmChannelHandle];

    if(Request <=  CANNM_TRIGGER_PASSIVE_STARTUP)
    {
        if(CANNM_TRIGGER_REQUEST == Request)
        {
            CanNm_NetworkRequest(nmChannelHandle);
        }
        else if(CANNM_TRIGGER_PASSIVE_STARTUP == Request)
        {
            CanNm_PassiveStartUp(nmChannelHandle);
        }
        else if(CANNM_TRIGGER_RELEASE == Request)
        {
            CanNm_NetworkRelease(nmChannelHandle);
        }
        else if(CANNM_TRIGGER_REPEAT_REQUEST == Request)
        {
            CanNm_RepeatMessageRequest(nmChannelHandle);
        }
        else
        {
            /* Do nothing */
        }        
    }
}
